const express = require('express');
const net = require('net');
const { spawn } = require('child_process'); // 引入 spawn
const WebSocket = require('ws');
const path = require('path');

// 创建一个Express应用
const app = express();
const wss = new WebSocket.Server({ noServer: true });
// 存储所有连接的 WebSocket 客户端
let clients = [];
let devices = [];
let isScanning = false;
let updateTime = updateScanTimestamp();
let elapsedTime = 0;

function updateScanTimestamp() {
  const options = { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false };
  return new Date().toLocaleString('zh-CN', options);
}

// 客户端连接到 WebSocket 时
wss.on('connection', (ws, req) => {
  const clientIP = req.connection.remoteAddress || req.socket.remoteAddress;
  console.log(`New client connected from IP: ${clientIP}`);

  // 将新的 WebSocket 客户端加入到 clients 列表中
  clients.push(ws);
  devices.forEach(dev => {
    // 立即发送已经扫描到的结果
    ws.send(JSON.stringify(dev));
  });
  broadcast({'elapsedTime': elapsedTime, 'updateTime': updateTime, 'clients': clients.length});

  // 当收到消息时（如开始扫描命令），启动扫描
  ws.on('message', async (message) =>  {
    console.log('Received message:' + message + " from " + clientIP);  // 打印收到的消息
    if (message == 'start_scan') {
      if (isScanning) {
        console.log('is scanning, skip');
      } else {
        const startTime = Date.now(); // 记录扫描开始时间

        devices = []
        broadcast({'reset': true});

        await scanNetwork();
    
        const endTime = Date.now(); // 记录扫描结束时间
        elapsedTime = endTime - startTime; // 计算扫描耗时（毫秒)
        updateTime = updateScanTimestamp();

        broadcast({'elapsedTime': elapsedTime, 'updateTime': updateTime, 'clients': clients.length});
      }
    }
  });

  // 监听客户端断开连接
  ws.on('close', () => {
    // 从 clients 中移除断开连接的客户端
    clients = clients.filter(client => client !== ws);
    console.log(`Client disconnected from IP: ${clientIP}`);
    broadcast({'elapsedTime': elapsedTime, 'updateTime': updateTime, 'clients': clients.length});
  });
});

// 网段设置（192.168.7.0/24）
const subnets = ['192.168.7.', '192.168.12.'];
const port = 5555;

// 扫描一个 IP 地址的端口是否开放
function checkPort(ip) {
  // console.log(`checkPort ${ip}`);
  return new Promise((resolve) => {
    const socket = new net.Socket();
    socket.setTimeout(2000); // 连接超时
    socket.on('connect', () => {
      socket.destroy();
      resolve(true); // 端口开放
    });
    socket.on('timeout', () => {
      socket.destroy();
      resolve(false); // 连接超时，端口未开放
    });
    socket.on('error', () => {
      socket.destroy();
      resolve(false); // 连接错误，端口未开放
    });
    socket.connect(port, ip); // 连接到目标端口
  });
}

// 执行 adb 命令获取设备名称
function getDeviceName(ip) {
  return new Promise((resolve, reject) => {
    // 使用 spawn 启动 adb 进程，windowsHide: true 避免弹出命令窗口
    const adbConnect = spawn('adb', ['connect', `${ip}:5555`], { windowsHide: true });
    
    adbConnect.on('close', (code) => {
      if (code !== 0) {
        reject(`Error connecting to ${ip}:5555`);
        return;
      }
      
      // 获取设备名称
      const adbShell = spawn('adb', ['-s', `${ip}:5555`, 'shell', "getprop ro.oem.product.name | tr -d '\n'; echo -n ' Model: '; getprop ro.product.model | tr -d '\n'; echo -n ', Android: '; getprop ro.build.version.release | tr -d '\n'; echo -n ', Build Date: '; getprop ro.build.date | tr -d '\n'"], { windowsHide: true });

      let deviceName = '';
      
      adbShell.stdout.on('data', (data) => {
        deviceName += data.toString(); // 处理命令的标准输出
      });

      adbShell.stderr.on('data', (data) => {
        console.error(`stderr: ${data}`);
        spawn('adb', ['disconnect', `${ip}:5555`], { windowsHide: true });
      });

      adbShell.on('close', (code) => {
        if (code !== 0) {
          // reject(`Error executing getprop on ${ip}`);
          resolve(undefined);
          return;
        }

        // 获取设备名称，去除多余的空格
        deviceName = deviceName.trim();
        
        // 断开连接
        const adbDisconnect = spawn('adb', ['disconnect', `${ip}:5555`], { windowsHide: true });
        
        adbDisconnect.on('close', (code) => {
          if (code !== 0) {
            console.error(`Error disconnecting from ${ip}`);
          }

          // 返回设备名称
          resolve(deviceName);
        });
      });
    });
  });
}

function broadcast(message) {
  clients.forEach(client => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify(message));
    }
  });
}

// 扫描整个子网的 IP（并行）
async function scanNetwork() {
  isScanning = true;
  const promises = [];
  for (let subnet of subnets) {
    console.log(`scan ${subnet}*`);
    for (let i = 10; i <= 254; i++) {
      const ip = `${subnet}${i}`;
      promises.push(
        checkPort(ip).then(async (isOpen) => {
          if (isOpen) {
            const deviceName = await getDeviceName(ip); // 获取设备名称
            if (deviceName == undefined) {
              return;
            }

            console.log(`found ${ip} ${deviceName}`);

            const device = { ip, deviceName };
            broadcast(device);
            devices.push(device);
          }
        }).catch(error => {
          console.log(`${ip} error: ${error}`);
        })
      );
    }
  }
  await Promise.all(promises);
  isScanning = false;
}

// 提供静态文件
app.use(express.static(path.join(__dirname, 'public')));  // 假设你的 HTML 文件放在 public 目录下
// 主页路由，返回前端页面
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

const serverPort = 3005;

// 启动服务器
const server = app.listen(serverPort, () => {
  console.log(`Server is running on http://localhost:${serverPort}`);
});

server.on('upgrade', (request, socket, head) => {
  wss.handleUpgrade(request, socket, head, (ws) => {
    wss.emit('connection', ws, request);
  });
});
